/*
 * Copyright 2007 www.luzand.com
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * XML Element Wrapper.
 */
function yrprxSimpleXMLElementWrapper(elem, doc)
{
    this.wrappedElement = elem;
    this.document = doc;
}

yrprxSimpleXMLElementWrapper.prototype.getNodeName = function()
{
    return this.wrappedElement.nodeName;
}

yrprxSimpleXMLElementWrapper.prototype.getElementsByTagName = function(tagName)
{
    return this.wrappedElement.getElementsByTagName(tagName);
}

yrprxSimpleXMLElementWrapper.prototype.enumerateElementsByTagName = function(tagName, handler, arg1, arg2, arg3)
{
    if (!tagName || !handler)
        return;

    try
    {
        var elems = this.getElementsByTagName(tagName);
        for (var i = 0, numOfElems = elems.length; i < numOfElems; ++i)
            handler(new yrprxSimpleXMLElementWrapper(elems[i], this.document), arg1, arg2, arg3);
    }
    catch(ex)
    {
        dump("ERROR yrprxSimpleXMLElementWrapper - enumerateElementsByTagName: Exception: " + ex + "\n");
    }
}

yrprxSimpleXMLElementWrapper.prototype.hasChildNodes = function()
{
    return this.wrappedElement.hasChildNodes();
}

yrprxSimpleXMLElementWrapper.prototype.enumerateChildElements = function(handler, arg1, arg2, arg3)
{
    if (!handler)
        return;

    try
    {
        var elems = this.wrappedElement.childNodes;
        for (var i = 0, numOfElems = elems.length; i < numOfElems; ++i)
        {
            if (elems[i].nodeType == Components.interfaces.nsIDOMNode.TEXT_NODE)
                continue;

            handler(new yrprxSimpleXMLElementWrapper(elems[i], this.document), arg1, arg2, arg3);
        }
    }
    catch(ex)
    {
        dump("ERROR yrprxSimpleXMLElementWrapper - enumerateChilds: Exception: " + ex + "\n");
    }
}

yrprxSimpleXMLElementWrapper.prototype.getAttribute = function(attributeName)
{
    var attribute = this.wrappedElement.getAttributeNode(attributeName);

    return !attribute ? null : attribute.value;
}

yrprxSimpleXMLElementWrapper.prototype.loadAttributes = function(obj, attributes)
{
    for (var i in attributes)
    {
        obj[attributes[i]] = this.getAttribute(attributes[i]);
    }
}

yrprxSimpleXMLElementWrapper.prototype.addAttribute = function(name, value)
{
    if (!value)
        return null;

    var attribute = this.document.createAttribute(name);

    attribute.value = value.toString();

    this.wrappedElement.setAttributeNode(attribute);

    return attribute;
}

yrprxSimpleXMLElementWrapper.prototype.saveAttributes = function(obj, attributes)
{
    for (var i in attributes)
    {
        this.addAttribute(attributes[i], obj[attributes[i]]);
    }
}

yrprxSimpleXMLElementWrapper.prototype.getNodeText = function()
{
    try
    {
        if (!this.wrappedElement.hasChildNodes())
            return null;

        var elems = this.wrappedElement.childNodes;
        for (var i = 0, numOfElems = elems.length; i < numOfElems; ++i)
        {
            if (elems[i].nodeType == Components.interfaces.nsIDOMNode.TEXT_NODE)
                return elems[i].nodeValue;
        }
    }
    catch(ex)
    {
        dump("ERROR yrprxSimpleXMLElementWrapper - getNodeText: Exception: " + ex + "\n");
    }
    return null;
}

yrprxSimpleXMLElementWrapper.prototype.getFirstNodeText = function(tagName)
{
    try
    {
        var nodes = this.getElementsByTagName(tagName);
        if (!nodes || !nodes.length)
            return null;

        return new yrprxSimpleXMLElementWrapper(nodes[0]).getNodeText();
    }
    catch(ex)
    {
        dump("ERROR yrprxSimpleXMLElementWrapper - getFirstNodeText: Exception: " + ex + "\n");
    }
    return null;
}

yrprxSimpleXMLElementWrapper.prototype.addNode = function(name, value)
{
    if (!name)
        throw "Empty node name!";

    var element = this.document.createElement(name);

    if (typeof value != "undefined")
    {
        element.appendChild(this.document.createTextNode(value));
    }

    this.wrappedElement.appendChild(element);

    return new yrprxSimpleXMLElementWrapper(element, this.document);
}

yrprxSimpleXMLElementWrapper.prototype.addText = function(value)
{
    this.wrappedElement.appendChild(this.document.createTextNode(value));

    return this;
}

/**
 * XML Builder.
 */
function yrprxSimpleXMLBuilder(rootElement, instruction)
{
    var doc = yrprxComponentsFactory.createXMLDocument();
    // add Instructions
    if (typeof instruction == "undefined")
        instruction = "version=\"1.0\" encoding=\"UTF-8\"";
    doc.appendChild(doc.createProcessingInstruction("xml", instruction));
    // create root
    var root = doc.createElement(rootElement);

    doc.appendChild(root);

    yrprxSimpleXMLElementWrapper.call(this, root, doc);
}

yrprxSimpleXMLBuilder.prototype = new yrprxSimpleXMLElementWrapper();

yrprxSimpleXMLBuilder.prototype.save = function(file)
{
    var stream = yrprxComponentsFactory.createSafeFileOutputStream(file);

    yrprxComponentsFactory.createXMLSerializer().serializeToStream(this.document, stream, "UTF-8");

    if (yrprxComponentsFactory.implementsIInputStream(stream))
        stream.finish();
    else
        stream.close();
}

yrprxSimpleXMLBuilder.prototype.toString = function()
{
    return yrprxComponentsFactory.createXMLSerializer().serializeToString(this.document);
}

/**
 * XML Parser.
 */
function yrprxSimpleXMLParser(source)
{
    if (yrprxComponentsFactory.implementsIDOMXMLDocument(source))
        yrprxSimpleXMLElementWrapper.call(this, source, source);
    else if (yrprxComponentsFactory.implementsIInputStream(source))
    {
        var xmlString = yrprxComponentsFactory.createScriptableInputStream(source).read(source.available());

        var xml = yrprxComponentsFactory.createDOMParser().parseFromString(xmlString, "application/xml");
        if (!xml) throw "Cannot parse XML";

        yrprxSimpleXMLElementWrapper.call(this, xml, xml);
    }
    else
    {
        if (!yrprxUtil.isFile(source) || !source.exists())
            throw "Cannot parse XML";

        var inputStream = yrprxComponentsFactory.createFileInputStream(source);
        try
        {
            var xmlString = yrprxComponentsFactory.createScriptableInputStream(inputStream).read(inputStream.available());

            var xml = yrprxComponentsFactory.createDOMParser().parseFromString(xmlString, "application/xml");
            if (!xml) throw "Cannot parse XML";

            yrprxSimpleXMLElementWrapper.call(this, xml, xml);
        }
        finally
        {
            inputStream.close();
        }
    }
}

yrprxSimpleXMLParser.prototype = new yrprxSimpleXMLElementWrapper();

